#include "mainwindow.h"

MainWindow::MainWindow() {
    isViewMode = true;
    isLoadMDFile = false;
    selectDialog = new CustomDialog();
    transferWindow = new TransferWindow();
    imageWindow = new ImageWindow();

    CreateMainWindow();
    CreateToolBar();
    statusBar() -> showMessage(tr("View Mode"));
    InitSDKEnvironment();
}

MainWindow::~MainWindow() {
    delete gWebView;
    delete gMarkdownEdit;
    delete gFileTree;
    delete gDBTree;
    delete gStackWin;
    delete gArrowLabel;
    delete selectDialog;
    delete transferWindow;
    delete imageWindow;

    ExitSDKEnvironment();
}

void MainWindow::CreateMainWindow() {
    setWindowTitle("QMarkDown");
    setWindowIcon(QIcon(":/material/Ui/apps_notes_24px.png"));

    int *size = new int[2];
    size = GetScreenSize();

    setMinimumSize(1280, 680);
    // setMaximumSize(size[0], size[1]);

    delete size;

    SetWidgets();
}

void MainWindow::SetWidgets() {
    QWidget *w = new QWidget();
    this -> setCentralWidget(w);

    gFileTree = new QTreeWidget();
    gFileTree -> setHeaderHidden(true);
    // gFileTree -> setSelectionMode(QAbstractItemView::SingleSelection);
    connect(gFileTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT(SlotFileTreeItemClicked()));
    gDBTree = new QTreeWidget();
    gDBTree -> setHeaderHidden(true);
    // connect(gDBTree, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this, SLOT());
    QVBoxLayout *leftLayout = new QVBoxLayout();
    leftLayout -> addWidget(gFileTree);
    leftLayout -> addWidget(gDBTree);

    gWebView = new QWebEngineView();
    gMarkdownEdit = new QTextEdit();
    gMarkdownEdit -> setEnabled(false);
    connect(gMarkdownEdit, SIGNAL(cursorPositionChanged()), this, SLOT(SlotTextEditCursorPositionChanged()));
    connect(gMarkdownEdit, SIGNAL(textChanged()), this, SLOT(SlotTextEditContentChanged()));
    // QWebEngineSettings *pWebSettings = gWebView -> settings();
    // gCodeEdit = new QsciScintilla();
    // gCodeEdit -> setMarginType(0, QsciScintilla::NumberMargin);
    // gCodeEdit -> setMarginLineNumbers(0, true);
    // gCodeEdit -> setMarginWidth(0, 20);

    gStackWin = new QStackedWidget();
    gStackWin -> addWidget(gWebView);
    gStackWin -> addWidget(gMarkdownEdit);

    gArrowLabel = new ClickedQLabel();
    gArrowLabel -> setPixmap(QPixmap::fromImage(QImage(":/material/Ui/arrow_right.png")));
    gArrowLabel -> setAlignment(Qt::AlignCenter);
    connect(gArrowLabel, SIGNAL(clicked()), this, SLOT(SlotArrowClicked()));

    QHBoxLayout *rightLayout = new QHBoxLayout();
    rightLayout -> addWidget(gStackWin);
    rightLayout -> addWidget(gArrowLabel);

    QHBoxLayout *layout = new QHBoxLayout();
    layout -> addLayout(leftLayout);
    layout -> addLayout(rightLayout);
    layout -> setStretchFactor(leftLayout, 1);
    layout -> setStretchFactor(rightLayout, 4);

    w -> setLayout(layout);
}

void MainWindow::CreateToolBar() {
    QToolBar *fileBar = addToolBar(tr("&File"));
    QToolBar *storageBar = addToolBar(tr("&Storage"));
    QToolBar *helpBar = addToolBar(tr("&Help"));
    QToolBar *transferBar = addToolBar(tr("&Transfer"));
    QToolBar *authorBar = addToolBar(tr("&author"));

    QAction *openFileAction = new QAction(QIcon(":/material/Ui/open_file.png"), tr("&open file"), this);
    connect(openFileAction, &QAction::triggered, this, &MainWindow::SlotOpenFile);
    fileBar -> addAction(openFileAction);

    QAction *openFolderAction = new QAction(QIcon(":/material/Ui/open_folder.png"), tr("&open folder"), this);
    connect(openFolderAction, &QAction::triggered, this, &MainWindow::SlotOpenFolder);
    fileBar -> addAction(openFolderAction);

    QAction *configBackendAction = new QAction(QIcon(":/material/Ui/config.png"), tr("&config"), this);
    connect(configBackendAction, &QAction::triggered, this, &MainWindow::SlotConfigBackend);
    storageBar -> addAction(configBackendAction);

    QAction *loginAction = new QAction(QIcon(":/material/Ui/people.png"), tr("&login"), this);
    connect(loginAction, &QAction::triggered, this, &MainWindow::SlotLogin);
    storageBar -> addAction(loginAction);

    QAction *uploadFileAction = new QAction(QIcon(":/material/Ui/cloud_upload.png"), tr("&upload"), this);
    connect(uploadFileAction, &QAction::triggered, this, &MainWindow::SlotUploadFile);
    storageBar -> addAction(uploadFileAction);

    QAction *downloadFileAction = new QAction(QIcon(":/material/Ui/cloud_download.png"), tr("&download"), this);
    connect(downloadFileAction, &QAction::triggered, this, &MainWindow::SlotDownloadFile);
    storageBar -> addAction(downloadFileAction);

    QAction *cloudDBAction = new QAction(QIcon(":/material/Ui/database.png"), tr("&database"), this);
    connect(cloudDBAction, &QAction::triggered, this, &MainWindow::SlotCloudDB);
    storageBar -> addAction(cloudDBAction);

    QAction *transferAction = new QAction(QIcon(":/material/Ui/transfer.png"), tr("&transfer"), this);
    connect(transferAction, &QAction::triggered, this, &MainWindow::SlotTransfer);
    transferBar -> addAction(transferAction);

    QAction *helpAction = new QAction(QIcon(":/material/Ui/help.png"), tr("&help"), this);
    connect(helpAction, &QAction::triggered, this, &MainWindow::SlotHelp);
    helpBar -> addAction(helpAction);

    QAction *githubAction = new QAction(QIcon(":/material/Ui/github_copyrighted.png"), tr("&github"), this);
    connect(githubAction, &QAction::triggered, this, &MainWindow::SlotForkProject);
    authorBar -> addAction(githubAction);

    QAction *payAction = new QAction(QIcon(":/material/Ui/pay.png"), tr("&pay"), this);
    connect(payAction, &QAction::triggered, this, &MainWindow::SlotPay);
    authorBar -> addAction(payAction);
}

void MainWindow::RemoveFileTreeItems(QTreeWidget* tree) {
    QTreeWidgetItemIterator it(tree);
    int i = 0;
    while (*it) {
        if((*it) -> parent() == Q_NULLPTR) {
            delete gFileTree -> takeTopLevelItem(0);
        } else {
            delete (*it) -> parent() -> takeChild(i);
            ++i;
        }
    }
}

void MainWindow::RemoveDBTreeItems(QTreeWidget* tree) {
    QTreeWidgetItemIterator it(tree);
    int i = 0;
    while (*it) {
        if((*it) -> parent() == Q_NULLPTR) {
            delete gFileTree -> takeTopLevelItem(i);
            ++i;
        }
    }
}

void MainWindow::MarkDown2HTML(const QString &m) {
    QFile fr(m);
    QFile fw(QDir::currentPath() + "/Github/QMarkDown/QMarkDown/index.html");
    if (fr.open(QFile::ReadOnly | QFile::Text)) {
        if (fw.open(QFile::WriteOnly | QFile::Text)) {
            QTextStream inputStream(&fw);
            QString prefix("<!DOCTYPE html>\n<html>\n<xmp theme=\"united\">\n");
            QString postfix("</xmp>\n<script src=\"strapdown/strapdown.js\"></script>\n</html>");
            inputStream << prefix;
            inputStream << fr.readAll();
            inputStream << postfix;
        } else {
            qDebug() << "Can't open html file!";
        }
        gWebView -> load(QUrl::fromLocalFile(QDir::currentPath() + "/Github/QMarkDown/QMarkDown/index.html"));
    } else {
        qDebug() << "Can't open markdown file!";
    }
    fw.close();
    fr.close();
}

void MainWindow::EditMarkDown(const QString &m) {
    QFile fr(m);
    if (fr.open(QFile::ReadOnly | QFile::Text)) {
        gMarkdownEdit -> setText(fr.readAll());
    }
    fr.close();
}

void MainWindow::ReadYAMLFile() {
    QString yamlPath = QDir::currentPath().toLocal8Bit() + "/Github/QMarkDown/QMarkDown/AccessKey.yaml";
    YAML::Node config = YAML::LoadFile(yamlPath.toStdString());

    std::string __EndPoint__;
    std::string __AccessKeyID__;
    std::string __AccessKeySecret__;

    QString EndPoint;
    QString AccessKeyID;
    QString AccessKeySecret;

    gAccessKey.clear();
    if (selectDialog -> isOSSSelected -> isChecked()) {
        __EndPoint__ =  config["AliCloud"]["EndPoint"].as<std::string>();
        __AccessKeyID__ =  config["AliCloud"]["AccessKeyID"].as<std::string>();
        __AccessKeySecret__ =  config["AliCloud"]["AccessKeySecret"].as<std::string>();

        EndPoint = QString::fromStdString(__EndPoint__);
        AccessKeyID = QString::fromStdString(__AccessKeyID__);
        AccessKeySecret = QString::fromStdString(__AccessKeySecret__);

        gAccessKey.append(AccessKeyID);
        gAccessKey.append(AccessKeySecret);
        gAccessKey.append(EndPoint);
    }
    else if (selectDialog -> isQiNiuSelected -> isChecked()) {
        __AccessKeyID__ =  config["QiNiuCloud"]["AccessKeyID"].as<std::string>();
        __AccessKeySecret__ =  config["QiNiuCloud"]["AccessKeySecret"].as<std::string>();

        AccessKeyID = QString::fromStdString(__AccessKeyID__);
        AccessKeySecret = QString::fromStdString(__AccessKeySecret__);

        gAccessKey.append(AccessKeyID);
        gAccessKey.append(AccessKeySecret);
    }
}

void MainWindow::SlotOpenFile() {
    std::string mainDirectory = GetMainDirectory();
    QString filePath = QFileDialog::getOpenFileName(this, tr("Select File"), QString::fromStdString(mainDirectory), tr("Markdown File(*.md)"));
    if (filePath != "") {
        gCurrentLoadFile = filePath;

        QStringList fileStringList = filePath.split("/");
        gAbsolutePath = "";
        for (int i = 0; i < fileStringList.size() - 1; ++i) {
            if (i == fileStringList.size() - 2) {
                gAbsolutePath.append(fileStringList.at(i));
            } else {
                gAbsolutePath.append(fileStringList.at(i));
                gAbsolutePath.append(tr("/"));
            }
        }
        QString fileName = fileStringList.at(fileStringList.size() - 1);

        RemoveFileTreeItems(gFileTree);

        QTreeWidgetItem *root = new QTreeWidgetItem();
        root -> setText(0, fileName);
        gFileTree -> addTopLevelItem(root);

        MarkDown2HTML(gCurrentLoadFile);
        isLoadMDFile = true;

        gMarkdownEdit -> setEnabled(true);
        EditMarkDown(gCurrentLoadFile);
    }
}

void MainWindow::SlotOpenFolder() {
    std::string mainDirectory = GetMainDirectory();
    QString path = QFileDialog::getExistingDirectory(this, tr("Open Folder"), QString::fromStdString(mainDirectory));
    if (path != "") {
        gWebView -> load(QUrl::fromLocalFile(QDir::currentPath() + "/Github/QMarkDown/QMarkDown/Html/index.html"));

        gAbsolutePath = path;

        QDir dir(path);
        QStringList filters;
        filters << "*.md";
        dir.setNameFilters(filters);

        QFileInfoList fileInfoList = dir.entryInfoList();
        QStringList fileStringList = path.split("/");
        QString pathName = fileStringList.at(fileStringList.size() - 1);

        RemoveFileTreeItems(gFileTree);

        QTreeWidgetItem *root = new QTreeWidgetItem();
        root -> setText(0, pathName);
        gFileTree -> addTopLevelItem(root);

        QVector<QTreeWidgetItem *> fileNameVector(fileInfoList.size());
        QString fileName;
        for (int i = 0; i < fileInfoList.size(); ++i) {
            QFileInfo fileInfo = fileInfoList.at(i);
            fileName = fileInfo.completeBaseName() + tr(".") + fileInfo.completeSuffix();
            fileNameVector[i] = new QTreeWidgetItem();
            fileNameVector[i] -> setText(0, fileName);
            root -> addChild(fileNameVector[i]);
        }

        gFileTree -> expandAll();
    }
}

void MainWindow::SlotArrowClicked() {
    isViewMode = !isViewMode;
    if (isViewMode) {
        gArrowLabel -> setPixmap(QPixmap::fromImage(QImage(":/material/Ui/arrow_right.png")));
        gArrowLabel -> setAlignment(Qt::AlignCenter);

        gStackWin -> setCurrentIndex(0);

        statusBar() -> showMessage(tr("View Mode"));
    }
    else {
        gArrowLabel -> setPixmap(QPixmap::fromImage(QImage(":/material/Ui/arrow_left.png")));
        gArrowLabel -> setAlignment(Qt::AlignCenter);

        gStackWin -> setCurrentIndex(1);

        size_t row;
        QTextCursor cursor = gMarkdownEdit -> textCursor();
        row = cursor.blockNumber() + 1;
        statusBar() -> showMessage(tr("Edit Mode - Line: ") + QString::number(row));
    }
}

void MainWindow::SlotTextEditCursorPositionChanged() {
    size_t row;
    QTextCursor cursor = gMarkdownEdit -> textCursor();
    row = cursor.blockNumber() + 1;
    statusBar() -> showMessage(tr("Edit Mode - Line: ") + QString::number(row));
}

void MainWindow::SlotTextEditContentChanged() {
    if (isLoadMDFile) {
        QFile fw(gCurrentLoadFile);
        if (fw.open(QFile::WriteOnly | QFile::Text)) {
            QTextStream inputStream(&fw);
            inputStream << gMarkdownEdit -> toPlainText();
        }
        fw.close();

        MarkDown2HTML(gCurrentLoadFile);
    }
}

void MainWindow::SlotLogin() {
    ReadYAMLFile();
    QMessageBox::about(NULL, tr("AccessKey"), tr("ID:        ") + gAccessKey.at(0) + tr("\n") + tr("Secret: ") + gAccessKey.at(1));
}

void MainWindow::SlotConfigBackend() {
    selectDialog -> show();
}

void MainWindow::SlotUploadFile() {
    std::string mainDirectory = GetMainDirectory();
    QString filePath = QFileDialog::getOpenFileName(this, tr("Select File"), QString::fromStdString(mainDirectory), tr("Markdown File(*.md)"));
    if (filePath != "") {
        QStringList fileStringList = filePath.split("/");
        QString fileName = fileStringList.at(fileStringList.size() - 1);
        QString objectName = QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss_ddd") + tr("_") + fileName;

        // RemoveDBTreeItems(gDBTree);

        if (selectDialog -> isOSSSelected -> isChecked()) {
            OSSSDKUploadAPI(filePath.toLocal8Bit().data(), objectName.toLocal8Bit().data());
        }
        else if (selectDialog -> isQiNiuSelected -> isChecked()) {
            qDebug() << "QiNiu";
        }
    }
}

void MainWindow::SlotDownloadFile() {
    if (selectDialog -> isOSSSelected -> isChecked()) {
        qDebug() << "OSS";
    }
    else if (selectDialog -> isQiNiuSelected -> isChecked()) {
        qDebug() << "QiNiu";
    }
}

void MainWindow::SlotCloudDB() {
    // RemoveDBTreeItems(gDBTree);

    QStringList fileList;
    if (selectDialog -> isOSSSelected -> isChecked()) {
        fileList = OSSSDKShowDataBaseAPI();
    }
    else if (selectDialog -> isQiNiuSelected -> isChecked()) {
        qDebug() << "QiNiu";
    }

    QVector<QTreeWidgetItem *> fileNameVector(fileList.size());
    for (int i = 0; i < fileList.size(); ++i) {
        fileNameVector[i] = new QTreeWidgetItem();
        fileNameVector[i] -> setText(0, fileList.at(i));
        gDBTree -> addTopLevelItem(fileNameVector[i]);
    }
}

void MainWindow::SlotTransfer() {
    transferWindow -> show();
}

void MainWindow::SlotHelp() {
    gWebView -> load(QUrl("http://daringfireball.net/projects/markdown/syntax"));
}

void MainWindow::SlotForkProject() {
    gWebView -> load(QUrl::fromLocalFile(QDir::currentPath() + "/Github/QMarkDown/QMarkDown/Html/project.html"));
}

void MainWindow::SlotPay() {
    imageWindow -> show();
}

void MainWindow::SlotFileTreeItemClicked() {
    QList<QTreeWidgetItem *> selectedItemList = gFileTree -> selectedItems();
    QString selectedItemText = selectedItemList.at(0) -> text(0);
    QRegularExpression re("^.*?\.(md)$");
    if (selectedItemText.contains(re)) {
        gCurrentLoadFile = gAbsolutePath + tr("/") + selectedItemText;

        MarkDown2HTML(gCurrentLoadFile);
        isLoadMDFile = true;

        gMarkdownEdit -> setEnabled(true);
        EditMarkDown(gCurrentLoadFile);
    }
}
